package top.codedance.iotp.client.net.handler;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import top.codedance.iotp.client.ClientApplication;
import top.codedance.iotp.common.constent.Command;
import top.codedance.iotp.common.entity.CommandTeam;
import top.codedance.iotp.common.entity.CommonEntity;
import top.codedance.iotp.common.entity.PluginResultEntity;
import top.codedance.iotp.common.executer.CommonClientPluginExecuter;
import cd.io.netty.channel.ChannelHandlerContext;
import cd.io.netty.channel.SimpleChannelInboundHandler;

import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Map;
import java.util.Set;
import java.util.UUID;

public class PluginsChannelHandler extends SimpleChannelInboundHandler<CommonEntity> {

    protected void messageReceived(final ChannelHandlerContext channelHandlerContext, final CommonEntity commonEntity) throws Exception {
        boolean isFindCommand = false;

        final CommonEntity innerCommonEntity = new CommonEntity();
        innerCommonEntity.setVersion(commonEntity.getVersion());
        innerCommonEntity.setCommand(commonEntity.getCommand());
        innerCommonEntity.setBody(commonEntity.getBody());
        Set<Map.Entry<CommandTeam, CommonClientPluginExecuter>> entries1 = ClientApplication.excuters.entrySet();
        for (Map.Entry<CommandTeam, CommonClientPluginExecuter> entry : entries1) {
            CommandTeam commandTeam = entry.getKey();
            if (commonEntity.getCommand() == commandTeam.getRequestCommand()) {
                final CommonClientPluginExecuter commonExecuter = entry.getValue();
                commonExecuter.setIniConfig(ClientApplication.ini);
                final String taskKey = UUID.randomUUID().toString();
                ClientApplication.asyncWorkerPool.submit(() -> {
                    commonExecuter.exec(channelHandlerContext, innerCommonEntity, taskKey);
                });
                isFindCommand = true;
                break;
            }
        }

        if(!isFindCommand) {
            Set<Map.Entry<CommandTeam, CommonClientPluginExecuter>> entries2 = ClientApplication.syncExcuters.entrySet();
            for (Map.Entry<CommandTeam, CommonClientPluginExecuter> entry : entries2) {
                CommandTeam commandTeam = entry.getKey();
                if (commonEntity.getCommand() == commandTeam.getRequestCommand()) {
                    final CommonClientPluginExecuter commonExecuter = entry.getValue();
                    commonExecuter.setIniConfig(ClientApplication.ini);
                    final CommonEntity tmpCommonEntity = new CommonEntity();
                    tmpCommonEntity.setVersion(commonEntity.getVersion());
                    tmpCommonEntity.setBody(commonEntity.getBody());
                    tmpCommonEntity.setCommand(commonEntity.getCommand());
                    tmpCommonEntity.setPackageLength(commonEntity.getPackageLength());
                    tmpCommonEntity.setHead(commonEntity.getHead());
                    ClientApplication.syncWorkerPool.submit(() -> {
                        PluginResultEntity pluginResultEntity = commonExecuter.exec(tmpCommonEntity.getBody(), UUID.randomUUID().toString());
                        byte[] results = JSONObject.toJSONString(pluginResultEntity, SerializerFeature.WriteMapNullValue, SerializerFeature.WriteNullStringAsEmpty).getBytes(StandardCharsets.UTF_8);
                        CommonEntity commonEntity2 = new CommonEntity();
                        commonEntity2.setVersion(tmpCommonEntity.getVersion());
                        commonEntity2.setCommand(commandTeam.getResponseCommand());
                        commonEntity2.setBody(results);
                        channelHandlerContext.writeAndFlush(commonEntity2);
                    });
                    isFindCommand = true;
                    break;
                }
            }
        }
        if (!isFindCommand && !Arrays.asList(Command.UPGRADE_RECEIVE, Command.REGISTER_RECEIVE).contains(commonEntity.getCommand())) {
            CommonEntity commonEntity2 = new CommonEntity();
            commonEntity2.setVersion(commonEntity.getVersion());
            commonEntity2.setCommand(Command.NONE);
            commonEntity2.setBody("unauthorized operation".getBytes(StandardCharsets.UTF_8));
            channelHandlerContext.writeAndFlush(commonEntity2);
        }
        channelHandlerContext.fireChannelRead(commonEntity); //向后传递
    }
}
